package com.github.tetrisgame.ui.view;

import static cn.bmob.v3.util.BLog.init;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;

import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;

import com.github.tetrisgame.R;
import com.github.tetrisgame.databinding.DialogChooseBinding;
import com.github.tetrisgame.utils.AlertDialogUtil;
import com.github.tetrisgame.utils.PermissionsUtils;
import com.github.tetrisgame.utils.UIUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/*
 支持圆形图片
 1. 支持圆形
 2. 设置边框
 3. 设置阴影
 4. 提供默认图片
 5. 从相册或者相机读取图片
 6. 从网络中获取图片
 7. 对图片进行缓存
 8. 点击效果
 */
public class CircularImageView extends View {
    //默认尺寸
    private int mSize = UIUtils.dp2px(200);
    //外层裁剪的形状
    private Path mOuterClipPath = new Path();
    //内层图片裁剪的形状
    private Path mImageCirclePath = new Path();
    //点按效果画笔
    private Paint mPressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //阴影画笔
    private Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //边框画笔
    private Paint  mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    //记录阴影的模糊半径
    private int mShadowRadius = 0;
    //记录阴影的颜色
    private int mShadowColor = Color.parseColor("#77000000");
    //边框尺寸
    private int mBorderWidth = 0;
    //边框颜色
    private int mBorderColor = Color.BLACK;
    //是否需要点按效果
    private boolean mShowPressEffect = false;
    //记录是按下还是抬手
    private boolean isPressed = false;
    //记录显示图片的矩形区域
    private Rect mImageRect;
    //相册启动器对象
    private ActivityResultLauncher<Intent> libraryLauncher;
    //相机启动器对象
    private ActivityResultLauncher<Uri> cameraLauncher;

    //代码中创建对象
    public CircularImageView(Context context) {
        this(context,null);
    }

    //xml中
    public CircularImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }
    //xml中
    public CircularImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        parseAttrs(attrs);
    }

    //解析自定义的属性
    private void parseAttrs(AttributeSet attrs){
        if (attrs == null) return;

        //从attrs中把所有自己定义的样式解析出来，保存到TypedArray中
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs,R.styleable.CircularImageView);
        //从typedArray对象中依次解析每一个属性即可
        mBorderWidth = typedArray.getDimensionPixelSize(R.styleable.CircularImageView_borderWidth,0);
        mBorderColor = typedArray.getColor(R.styleable.CircularImageView_borderColor,Color.BLACK);
        mShadowRadius = typedArray.getDimensionPixelSize(R.styleable.CircularImageView_shadowRadius,0);
        mShadowColor = typedArray.getColor(R.styleable.CircularImageView_shadowColor,Color.parseColor("#77000000"));
        mShowPressEffect = typedArray.getBoolean(R.styleable.CircularImageView_showPressEffect,false);
        //释放TypedArray对象
        typedArray.recycle();

        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);

        if (mShadowRadius > 0) {
            mShadowPaint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor);
        }
    }

    //基础配置
    private void init(){
        //点按效果
        mPressPaint.setStyle(Paint.Style.FILL);
        mPressPaint.setColor(Color.parseColor("#11FFFFFF"));

        //配置边框画笔
        mBorderPaint.setStyle(Paint.Style.STROKE);

        //创建好相册启动器对象
        ComponentActivity activity = (ComponentActivity) getContext();
        libraryLauncher = activity.registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                activityResult -> {
                    //判断是否有返回结果
                    if (activityResult.getResultCode() == Activity.RESULT_OK){
                        Intent intent = activityResult.getData();
                        Uri fileUri = intent.getData();

                        //将Uri对应的图片显示到自己的头像上
                        //Uri -> Bitmap
                        //InputStream 输入流  OutputStream 输出流 : 字节流
                        //FileInputStream
                        //BufferedInputStream

                        //Reader 字符输入流   Writer 字符输出流  ： 字符流
                        //输入流和输出流都是相对于内存而言

                        //网站上的一个视频下载到磁盘中 Acitivty ContentProvider
                        InputStream is = null;
                        try {
                            //使用内容解析器解析相册提供者提供的图片资源
                            is = getContext().getContentResolver().openInputStream(fileUri);
                            //将这个图片输入流 转化为Bitmap对象
                            mBitmap = BitmapFactory.decodeStream(is);
                            //刷新
                            invalidate();
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            if (is != null){
                                try {
                                    is.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }

                    }
                });

        //创建相机启动器对象
        cameraLauncher = activity.registerForActivityResult(
                new ActivityResultContracts.TakePicture(),
                result -> {
                    if (result){ //拍照成功
                        //读取内容提供者绑定的文件即可 head.jpg
                        String path = getContext().getFilesDir()+"/head.jpg";
                        mBitmap = BitmapFactory.decodeFile(path);
                        invalidate();
                    }
                }
        );
    }

    /*
     下面这些set方法就是暴露给外部在代码中设置属性
     */
    public void setBorderWidth(int width){
        this.mBorderWidth = width;
        mBorderPaint.setStrokeWidth(mBorderWidth);
    }
    public void setBorderColor(int color){
        this.mBorderColor = color;
        mBorderPaint.setColor(mBorderColor);
    }
    public void setShowPressEffect(boolean show){
        this.mShowPressEffect = show;
    }
    public void setShadowColor(int color){
        this.mShadowColor = color;
        mShadowPaint.setColor(mShadowColor);
    }
    public void setShadowRadius(int radius){
        this.mShadowRadius = radius;
        if (mShadowRadius > 0) {
            mShadowPaint.setShadowLayer(mShadowRadius, 0, 0, Color.parseColor("#72000000"));
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //确定自己想要的尺寸
        int desiredWidth = mSize;
        int desiredHeight = mSize;

        //根据父容器给到的约束获取真实的尺寸
        int realWidth = resolveSizeAndState(desiredWidth,widthMeasureSpec,MEASURED_STATE_TOO_SMALL);
        int realHeight = realWidth;

        //将最终的尺寸设置给视图
        setMeasuredDimension(realWidth,realHeight);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //配置外层需要裁剪的形状
        mOuterClipPath.addCircle(getWidth()/2f,
                getHeight()/2f,
                getWidth()/2f,
                Path.Direction.CW);
        //配置内层图片需要裁剪的形状
        mImageCirclePath.addCircle(getWidth()/2f,
                getHeight()/2f,
                getWidth()/2f-mShadowRadius-mBorderWidth,
                Path.Direction.CW);
        //确定图片的矩形区域
        mImageRect = new Rect(
                mShadowRadius+mBorderWidth,
                mShadowRadius+mBorderWidth,
                getWidth()-mShadowRadius-mBorderWidth,
                getHeight()-mShadowRadius-mBorderWidth
        );
    }

    private Bitmap mBitmap;
    private Bitmap getBitmap(){
        if (mBitmap == null){
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg_image);
        }
        return  mBitmap;
    }
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        //将外层的canvas裁剪为圆形
        //如果是常规的矩形 clipRect 其他形状使用clipPath
        //首先得确定好裁剪的路径Path
        canvas.clipPath(mOuterClipPath);

        //绘制阴影
        if (mShadowRadius > 0) {
            canvas.drawCircle(getWidth() / 2f,
                    getHeight() / 2f,
                    getWidth() / 2f - mShadowRadius,
                    mShadowPaint);
        }

        //绘制边框
        if (mBorderWidth > 0) {
            canvas.drawCircle(getWidth() / 2f,
                    getHeight() / 2f,
                    getWidth() / 2f - mShadowRadius - mBorderWidth/2f,
                    mBorderPaint);
        }

        //裁剪显示圆形图片的图层
        canvas.save();
        canvas.clipPath(mImageCirclePath);
        canvas.drawBitmap(getBitmap(),null,mImageRect,null);
        canvas.restore();

        //绘制点按效果
        if (mShowPressEffect && isPressed) {
            canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f - mShadowRadius-mBorderWidth, mPressPaint);
        }


    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!mShowPressEffect) return true;

        if (event.getAction() == MotionEvent.ACTION_DOWN){
            isPressed = true;
            invalidate();
            if (PermissionsUtils.sharedInstance.checkPermission(Manifest.permission.CAMERA)){
                //有权限
                showDialog();
            }else{
                //没有权限 去申请
                PermissionsUtils.sharedInstance.requestPermission(Manifest.permission.CAMERA,granted ->{
                    //请求结果
                    if (granted){
                        showDialog();
                    }
                });
            }
        }
        if (event.getAction() == MotionEvent.ACTION_UP){
            isPressed = false;
            invalidate();
        }
        return true;
    }

    //弹出提示框
    private void showDialog(){
        //创建布局解析器
        LayoutInflater inflater = LayoutInflater.from(getContext());
        //使用这个布局解析器去解析binding类对象
        DialogChooseBinding binding = DialogChooseBinding.inflate(inflater);
        AlertDialogUtil<DialogChooseBinding> dialog = new AlertDialogUtil<DialogChooseBinding>(binding) {
            @Override
            public void initEvent(DialogChooseBinding binding) {
                super.initEvent(binding);
                //取消按钮事件
                binding.btnCancel.setOnClickListener(v ->{
                    dismiss();
                });
                //相册按钮
                binding.btnLibrary.setOnClickListener(v ->{
                    dismiss();

                    //启动相册启动器对象
                    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    libraryLauncher.launch(intent);
                });
                //相机
                binding.btnCamera.setOnClickListener(v ->{
                    dismiss();
                    //自己在Files目录下创建一个文件用于保存视频或者照片
                    //xx/Files  /head.jpeg
                    //创建文件路径对应的文件对象
                    File file = new File(getContext().getFilesDir(),"head.jpg");

                    //创建文件
                    if (!file.exists()){
                        try {
                            file.createNewFile();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }

                    //将当前的这个文件对象和内容提供者关联
                    Uri uri = FileProvider.getUriForFile(
                            getContext(),
                            "com.github.tetrisgame.fileprovider",
                            file
                    );
                    cameraLauncher.launch(uri);
                });
            }
        };

        dialog.show();
    }

    //绘制三角形
    private void drawTriangle(){
        mOuterClipPath.moveTo(getWidth()/2f,0);
        mOuterClipPath.lineTo(0,getHeight());
        mOuterClipPath.lineTo(getWidth(),getHeight());
        mOuterClipPath.close();
    }

    //绘制圆形
    private void drawCircle(){
        mOuterClipPath.moveTo(getWidth()/2f,0);
        mOuterClipPath.lineTo(getWidth()/2f,getHeight()/2f);
        mOuterClipPath.addCircle(getWidth()/2f,getHeight()*3/4f,getHeight()/4f, Path.Direction.CW);
        mOuterClipPath.lineTo(getWidth(),0);
    }

    private void drawBezel(){
        mOuterClipPath.moveTo(0,getHeight()/2f);
        mOuterClipPath.cubicTo(
                getWidth()/4f,
                0,
                getWidth()*3/4f,
                getHeight(),
                getWidth(),
                getHeight()/2f);
        mOuterClipPath.close();
    }

    private void drawArc(){
        mOuterClipPath.addArc(
                UIUtils.dp2pxF(2),
                UIUtils.dp2pxF(2),
                getWidth()-UIUtils.dp2pxF(2),
                getHeight()-UIUtils.dp2pxF(2),0f,360
        );
    }

    private void drawImage(Canvas canvas){
        //添加一张图片
        canvas.save();
        //对canvas做额外操作 裁剪 旋转 移动
        canvas.clipPath(mImageCirclePath);
        Rect rect = new Rect(
                UIUtils.dp2px(20),
                UIUtils.dp2px(20),
                getWidth()-UIUtils.dp2px(20),
                getHeight()-UIUtils.dp2px(20)
        );
        canvas.drawBitmap(getBitmap(),null,rect,null);
        //恢复
        canvas.restore();
    }
}













